import java.util.LinkedList;

/**
 * This class receives orders from the OrderTread (which gets and constructs orders from the
 * database) and transmits them to the concerned client. This is only done if the concerned
 * client is actually connected to the server.
 *
 * @author Alexandre Dos Santos Coelho
 */
public class TransmitOrderThread extends Thread {

  private Server server; // Attached server
  private int delay; // Delay between two attempts to send orders queue
  private boolean running = true; // Determines if the thread is running
  private LinkedList<Order> orders = new LinkedList<Order>(); // Orders queue

  /**
   * Constructor. Creates and starts the order transmit thread.
   *
   * @param s Attached server
   * @param d Delay between two attemps to send orders queue
   */
  public TransmitOrderThread(Server s, int d) {
    server = s;
    delay = d;
    this.start();
  }

  /**
   * Adds an order to the sending queue
   * @param order Order to add in queue
   */
  public synchronized void addOrder(Order order) {

    boolean exists = false; // Determines if the order has already been inserted in queue
    for (Order o : orders) {
      if (o.getId() == order.getId()) {
        exists = true;
      }
    }

    // Adding in queue if the order doesn't exist
    if (!exists) {
      orders.add(order);
    }
  }

  /**
   * Thread run method. Attempts periodically to send the whole orders queue to the concerned
   * clients. An order will only be send if the concerned client is actually connected to the server.
   */
  public void run() {
    while (running) {
      synchronized (this) {
        try {
          Thread.sleep((long) (delay * 1000.0));
          LinkedList<Order> toDelete = new LinkedList<Order>(); // Orders to delete

          for (Order o : orders) { // Transmit orders to connected machines
            if (server.clientExists(o.getMachineId())) {
              server.getClient(o.getMachineId()).sendOrder(o);
              System.out.println(Logger.getTime() + "Sent order " + o + " to machine " + o.getMachineId());
              toDelete.add(o);
            }
          }

          for (Order o : toDelete) { // Deleting transmitted orders
            orders.remove(o);
            server.getDataManager().removeOrder(o);
          }
        } catch (InterruptedException ex) {}
      }
    }
  }
}
